package com.kun.portal.webframe.service;

import com.kun.portal.webframe.dao.AppointmentDao;
import com.kun.portal.webframe.dao.FlightPlaneDao;
import com.kun.portal.webframe.po.AppointmentPo;


import com.kun.portal.webframe.po.FlightPlanePo;
import com.kun.portal.webframe.po.FwUserPo;

import com.kun.portal.webframe.util.*;
import com.kun.portal.webframe.util.MessageFormatImp.*;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;

import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.data.domain.Pageable;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.TemporalType;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.persistence.criteria.Predicate;

/**
 * Created by Administrator on 2018/4/25.
 */
@Service
public class AppointmentService {
    @Autowired
    private AppointmentDao appointmentDao;
    @Autowired
    private EntityManager entityManager;
    @Autowired
    private  MessagePushService messagePushService;
    @Autowired
    private FlightPlaneDao flightPlaneDao;
    @Transactional
    public AppointmentPo addAppointment(AppointmentPo appo , FwUserPo fwUserPo) {

        MessageEmit.emit(fwUserPo,new AddAppointment(appo),MessageFilter.MessageType.addAppointment,messagePushService);
        appo.setEnterPerson(fwUserPo);
        return (AppointmentPo)this.appointmentDao.save(appo);
    }
    @Transactional
    public AppointmentPo editAppointment(AppointmentPo appo,FwUserPo fwUserPo) {
/*修改预约信息推送*/
        MessageEmit.emit(fwUserPo,new EditAppointment(appo),MessageFilter.MessageType.editAppointment,messagePushService);
        appo.setEnterPerson(fwUserPo);
        return (AppointmentPo)this.appointmentDao.save(appo);
    }
    /*车辆派遣预约信息修改*/
    @Transactional
    public AppointmentPo editAppointment(AppointmentPo appo) {
        return (AppointmentPo)this.appointmentDao.save(appo);
    }
    @Transactional
    public AppointmentPo  passAppointment(AppointmentPo appo,FwUserPo fwUserPo) {
/*预约取消信息推送*/
        MessageEmit.emit(fwUserPo,new PassAppointment(appo),MessageFilter.MessageType.passAppointment,messagePushService);
        appo.setEnterPerson(fwUserPo);
        return (AppointmentPo)this.appointmentDao.save(appo);
    }

    @Transactional
    public AppointmentPo saveAppointmentAndFlight(AppointmentPo appo,FwUserPo fwUserPo) {
        if(appo.getFlightPlane()!=null){
            appo.getFlightPlane().setFlightInfo(appo.getFlightInfo());
            appo.getFlightPlane().setExpectDate(appo.getAppoDate());
            //appo.getFlightPlane().setEstimatedTime(appo.getEstimatedTime());
            flightPlaneDao.save(appo.getFlightPlane());
        }
        /*预约航班预计划修改信息推送*/
        MessageEmit.emit(fwUserPo,new PrePlaneEdit(appo),MessageFilter.MessageType.prePlaneEdit,messagePushService);
        appo.setEnterPerson(fwUserPo);
        return (AppointmentPo)this.appointmentDao.save(appo);
    }
    @Transactional
    public AppointmentPo saveAppointmentAndFlightPlane(AppointmentPo appo,FwUserPo fwUserPo) {
        if(appo.getFlightPlane()!=null){
            appo.getFlightPlane().setFlightInfo(appo.getFlightInfo());
            appo.getFlightPlane().setExpectDate(appo.getAppoDate());
            appo.getFlightPlane().setEstimatedTime(appo.getEstimatedTime());
            flightPlaneDao.save(appo.getFlightPlane());
        }
        /*预约航班计划修改信息推送*/
        MessageEmit.emit(fwUserPo,new AppoFlightPlaneEdit(appo),MessageFilter.MessageType.appoFlightPlaneEdit,messagePushService);
        appo.setEnterPerson(fwUserPo);
        return (AppointmentPo)this.appointmentDao.save(appo);
    }

    public AppointmentPo transFormToFlightPlane(AppointmentPo appointmentPo,FwUserPo fwUserPo) {
        FlightPlanePo flightPlanePo =appointmentPo.getFlightPlane();
        flightPlanePo.setFlightInfo(appointmentPo.getFlightInfo());
        flightPlanePo.setDestination(appointmentPo.getDestination());
        flightPlanePo.setExpectDate(appointmentPo.getAppoDate());
        flightPlanePo.setImportOrExport(appointmentPo.getAppProperty());
        flightPlanePo.setOriginating(appointmentPo.getOriginating());

        flightPlanePo.setPlaneProperty("预约");
        flightPlanePo=flightPlaneDao.save(flightPlanePo);
        appointmentPo.setFlightPlane(flightPlanePo);
        appointmentPo.setHasTransformToPlane(true);
        MessageEmit.emit(fwUserPo,new TransformToFlightPlane(appointmentPo),MessageFilter.MessageType.transFormToFlightPlane,messagePushService);

        return (AppointmentPo)this.appointmentDao.save(appointmentPo);
    }

    public AppointmentPo throughAudit(AppointmentPo appo,FwUserPo userPo) {
        appo.setOrderStatus(Status.THROUGH_AUDIT);
        MessageEmit.emit(userPo,new ThroughAudit(appo),MessageFilter.MessageType.throughAudit,messagePushService);
        appo = appointmentDao.save(appo);
        return appo;
    }
    public AppointmentPo publishFlightPlane(AppointmentPo appo,FwUserPo fwUserPo) {
        if(appo.getFlightPlane()!=null){
            appo.getFlightPlane().setPlaneRunStatus(Status.PUBLISHED);
            FlightPlanePo flightPlanePo=flightPlaneDao.save(appo.getFlightPlane());
            appo.setFlightPlane(flightPlanePo);
        }
          /*预约航班预计划修改信息推送*/
        MessageEmit.emit(fwUserPo,new PrePlanePublish(appo),MessageFilter.MessageType.prePlanePublish,messagePushService);
        appo.setEnterPerson(fwUserPo);
        return appo;
    }

    public Page<AppointmentPo> findAllvehicleOfAppo(Pageable page,String appoUnit, String appoName, String appoPhoneNum, Date appoDate){
        Specification query = new Specification<AppointmentPo>() {
            @Override
            public javax.persistence.criteria.Predicate toPredicate(Root<AppointmentPo> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<javax.persistence.criteria.Predicate> pre= new ArrayList<>();
                if(StringUtils.isNotBlank(appoUnit)){
                    pre.add(cb.like(root.get("appoUnit"), "%"+appoUnit+"%"));
                }
                if(StringUtils.isNotBlank(appoName)){
                    pre.add(cb.like(root.get("appoName"), "%"+appoName+"%"));
                }
                if(StringUtils.isNotBlank(appoPhoneNum)){
                    pre.add(cb.like(root.get("appoPhoneNum"), "%"+appoPhoneNum+"%"));
                }
                if(null != appoDate){
                    pre.add(cb.like(root.get("appoDate"), "%"+appoDate+"%"));
                }
                Predicate predicate = cb.and(pre.toArray(new Predicate[pre.size()]));
                return predicate;
            }
        };
        return appointmentDao.findAll(query,page);
    }
    public Page<AppointmentPo> query(Pageable pageable, String unit, String phoneNUm, Date startDate, Date endDate,String status,String importOrExport){
        String sql = "select a from AppointmentPo a left join fetch  a.flightPlane f left join fetch f.flightInfo left join a.flightInfo where 1=1 ";
        if(null != startDate){
            sql += " and a.appoDate >= :startDate ";
        }
        if(null != endDate){
            sql += " and a.appoDate <= :endDate ";
        }
        if(StringUtils.isNotBlank(importOrExport)){
            sql+= " and  a.appProperty = '"+importOrExport+"' ";
        }

        if(StringUtils.isNotBlank(phoneNUm) ){
            sql += " and a.appoPhoneNum like '%"+phoneNUm+"%' ";

        }
        if(StringUtils.isNotBlank(unit)){
            sql += " and a.appoUnit like '%"+unit+"%'  ";

        }
//                String orSql = "";
//                if(StringUtils.isNotBlank(status)){
//
//                  if(status.indexOf("未审核")!=-1){
//                      orSql = " a.status = '未审核' ";
////                      pre=cb.equal(root.get("status"),"未审核");
//                  }
//
//                  if(status.indexOf("审核通过")!=-1){
//                      if(StringUtils.isNotBlank(orSql)){
//                          orSql += " or a.status='审核通过' ";
//
//                      }else{
//                          orSql += " a.status='审核通过' ";
//                      }
//                    }
//                    if(status.indexOf("审核取消")!=-1){
//                        if(StringUtils.isNotBlank(orSql)){
//                            orSql += " or a.status='审核取消' ";
//                          }else{
//                            orSql += " a.status='审核取消' ";
//                        }
//                    }
//                    if(status.indexOf("预约取消")!=-1){
//                        if(StringUtils.isNotBlank(orSql)){
//                            orSql += " or a.effective=false ";
//                        }else{
//                            orSql += " a.effective=false ";
//                        }
//                    }else{
//                        sql+="and a.effective= true ";
//                    }
//                    if(StringUtils.isNotBlank(orSql)){
//                        sql += " and ("+orSql+")";
//                    }
//                }

        Query query = entityManager.createQuery(sql);
        if(null != startDate){
            query.setParameter("startDate",startDate,TemporalType.TIMESTAMP);
        }
        if(null != endDate){
            query.setParameter("endDate",startDate,TemporalType.TIMESTAMP);
        }
        return  new PageImpl<AppointmentPo>(query,pageable);

//        Specification query = new Specification<AppointmentPo>() {
//            @Override
//            public javax.persistence.criteria.Predicate toPredicate(Root<AppointmentPo> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
//                List<javax.persistence.criteria.Predicate> predicates = new ArrayList<>();
//
//                if(null != startDate){
//                    predicates.add(cb.greaterThan(root.get("appoDate"), startDate));
//                }
//                if(null != endDate){
//                    predicates.add(cb.lessThan(root.get("appoDate"), endDate));
//                }
//                if(StringUtils.isNotBlank(phoneNUm) ){
//                    predicates.add(cb.like(root.get("appoPhoneNum"), "%"+phoneNUm+"%"));
//                }
//                if(StringUtils.isNotBlank(unit)){
//                    predicates.add(cb.like(root.get("appoUnit"), "%"+unit+"%"));
//                }
//                Predicate predicate = cb.and(predicates.toArray(new Predicate[predicates.size()]));
//                if(StringUtils.isNotBlank(status)){
//                    Predicate pre=null;
//                  if(status.indexOf("未审核")!=-1){
//                      pre=cb.equal(root.get("status"),"未审核");
//                  }
//
//                  if(status.indexOf("审核通过")!=-1){
//                      if(pre!=null){
//                          pre=cb.or(pre,cb.equal(root.get("status"),"审核通过"));
//
//                      }else{
//                          pre= cb.equal(root.get("status"),"审核通过");
//                      }
//                    }
//                    if(status.indexOf("审核取消")!=-1){
//                        if(pre!=null){
//                            pre=cb.or(pre,cb.equal(root.get("status"),"审核取消")) ;
//
//                        }else{
//                            pre= cb.equal(root.get("status"),"审核取消");
//                        }
//                    }
//                    if(status.indexOf("预约取消")!=-1){
//                        if(pre!=null){
//                            pre=cb.or(pre,cb.equal(root.get("status"),"预约取消"));
//
//                        }else{
//                            pre= cb.equal(root.get("status"),"预约取消");
//                        }
//                    }
//                    if(pre !=null){
//                        return cb.and(predicate,pre);
//                    }
//                }
//
//                return predicate;
//            }
//        };
//        return appointmentDao.findAll(query,  page);
    }


    public Page<AppointmentPo> queryNew(Pageable pageable, String unit, String phoneNUm, Date startDate, Date endDate,String status,String importOrExport){
        String sql = "select a from AppointmentPo a   left join a.flightInfo where 1=1 ";
        if(null != startDate&&null != endDate){
            sql += " and a.appoDate between :startDate and :endDate ";
        }
//        if(null != endDate){
//            sql += " and a.appoDate <= :endDate ";
//        }
        if(StringUtils.isNotBlank(importOrExport)){
            sql+= " and  a.appProperty = '"+importOrExport+"' ";
        }

        if(StringUtils.isNotBlank(phoneNUm) ){
            sql += " and a.appoPhoneNum like '%"+phoneNUm+"%' ";

        }
        if(StringUtils.isNotBlank(unit)){
            sql += " and a.appoUnit like '%"+unit+"%'  ";

        }
//                String orSql = "";
//                if(StringUtils.isNotBlank(status)){
//
//                  if(status.indexOf("未审核")!=-1){
//                      orSql = " a.status = '未审核' ";
////                      pre=cb.equal(root.get("status"),"未审核");
//                  }
//
//                  if(status.indexOf("审核通过")!=-1){
//                      if(StringUtils.isNotBlank(orSql)){
//                          orSql += " or a.status='审核通过' ";
//
//                      }else{
//                          orSql += " a.status='审核通过' ";
//                      }
//                    }
//                    if(status.indexOf("审核取消")!=-1){
//                        if(StringUtils.isNotBlank(orSql)){
//                            orSql += " or a.status='审核取消' ";
//                          }else{
//                            orSql += " a.status='审核取消' ";
//                        }
//                    }
//                    if(status.indexOf("预约取消")!=-1){
//                        if(StringUtils.isNotBlank(orSql)){
//                            orSql += " or a.effective=false ";
//                        }else{
//                            orSql += " a.effective=false ";
//                        }
//                    }else{
//                        sql+="and a.effective= true ";
//                    }
//                    if(StringUtils.isNotBlank(orSql)){
//                        sql += " and ("+orSql+")";
//                    }
//                }

        Query query = entityManager.createQuery(sql);
        if(null != startDate){
            query.setParameter("startDate",startDate,TemporalType.TIMESTAMP);
        }
        if(null != endDate){
            query.setParameter("endDate",startDate,TemporalType.TIMESTAMP);
        }
        return  new PageImpl<AppointmentPo>(query,pageable);

    }


    public List<AppointmentPo> queryAppointmnetAndPlaneNoPage(Pageable pageable, String flightInfoId, Date exceptDateS,Date exceptDateE, Date estimatedTimeS,  Date estimatedTimeE,String importOrExport){

        String sql = "select a from AppointmentPo a left join fetch  a.flightPlane f left join fetch f.flightInfo left join a.flightInfo where " +
                "((f is not null and f.planeRunStatus between "+Status.EFFECTIVE+" and "+Status.COMPLETED+")or (f is null )) ";
        if(null != exceptDateS&&null!=exceptDateE){
            sql += " and  "+ DatabaseAdapter.toDate("a.appoDate" )+"  between :exceptDateS and :exceptDateE";
        }
        if(null != estimatedTimeS&&null!=estimatedTimeE){
            sql += " and f.estimatedTime between  :estimatedTimeS  and :estimatedTimeE ";
        }
        if(StringUtils.isNotBlank(importOrExport)){
            sql+= " and  (a.appProperty = '"+importOrExport+"' or  a.appProperty = '中转联程') ";
        }

        if(StringUtils.isNotBlank(flightInfoId) ){
            sql += " and a.flightInfo.flightInfoId  = '"+flightInfoId+"' ";

        }
        if(pageable.getSort() !=null){
            sql+="order by a."+(pageable.getSort().toString().replace(':',' '));
            System.out.println(pageable.getSort().toString().replace(':',' '));
        }
        Query query = entityManager.createQuery(sql);
        if(null != exceptDateS&&null!=exceptDateE){
            query.setParameter("exceptDateS",exceptDateS,TemporalType.DATE);
            query.setParameter("exceptDateE",exceptDateE,TemporalType.DATE);
        }
        if(null != estimatedTimeS&&null!=estimatedTimeE){
            query.setParameter("estimatedTimeS",estimatedTimeS,TemporalType.DATE);
            query.setParameter("estimatedTimeE",estimatedTimeE,TemporalType.DATE);
        }

        return  query.getResultList();

    }

    public List<AppointmentPo> queryAppointmnetPlaneNoPage(Pageable pageable, String flightInfoId, Date exceptDateS,Date exceptDateE, Date estimatedTimeS,  Date estimatedTimeE,String importOrExport){
        String sql = "select a from AppointmentPo a right join fetch  a.flightPlane f left join fetch f.flightInfo left join a.flightInfo where a.flightPlane is not null  ";
        if(null != exceptDateS&&null!=exceptDateE){
            sql += " and a.appoDate  between :exceptDateS and :exceptDateE";
        }
        if(null != estimatedTimeS&&null!=estimatedTimeE){
            sql += " and a.estimatedTime between  :estimatedTimeS  and :estimatedTimeE ";
        }
        if(StringUtils.isNotBlank(importOrExport)){
            sql+= " and  (a.appProperty = '"+importOrExport+"' or  a.appProperty = '中转联程') ";
        }

        if(StringUtils.isNotBlank(flightInfoId) ){
            sql += " and a.flightInfo.flightInfoId  = '"+flightInfoId+"' ";

        }
        if(pageable.getSort() !=null){
            sql+="order by a."+(pageable.getSort().toString().replace(':',' '));
            System.out.println(pageable.getSort().toString().replace(':',' '));
        }
        Query query = entityManager.createQuery(sql);
        if(null != exceptDateS&&null!=exceptDateE){
            query.setParameter("exceptDateS",exceptDateS,TemporalType.DATE);
            query.setParameter("exceptDateE",exceptDateE,TemporalType.DATE);
        }
        if(null != estimatedTimeS&&null!=estimatedTimeE){
            query.setParameter("estimatedTimeS",estimatedTimeS,TemporalType.DATE);
            query.setParameter("estimatedTimeE",estimatedTimeE,TemporalType.DATE);
        }

        return  query.getResultList();


    }


    public List<AppointmentPo> queryAppointmentPublishedFlightPlane(Pageable pageable, String flightInfoId, Date exceptDateS,Date exceptDateE, Date estimatedTimeS,  Date estimatedTimeE,String importOrExport){
        String sql = "select a from AppointmentPo a left join fetch  a.flightPlane f left join fetch f.flightInfo left join a.flightInfo where  " +
                " a.orderStatus between "+Status.THROUGH_AUDIT+" and "+(Status.COMPLETED-1)+" " +
                " and f.planeRunStatus between "+Status.PUBLISHED+" and "+(Status.COMPLETED-1)+"";
        if(null != exceptDateS&&null!=exceptDateE){
            sql += " and "+DatabaseAdapter.toDate("a.appoDate")+"  between :exceptDateS and :exceptDateE";
        }
        if(null != estimatedTimeS&&null!=estimatedTimeE){
            sql += " and "+DatabaseAdapter.toDate("a.estimatedTime")+" between  :estimatedTimeS  and :estimatedTimeE ";
        }
        if(StringUtils.isNotBlank(importOrExport)){
            sql+= " and ( a.appProperty = '"+importOrExport+"'  or a.appProperty = '中转联程') ";
        }

        if(StringUtils.isNotBlank(flightInfoId) ){
            sql += " and a.flightInfo.flightInfoId  = '"+flightInfoId+"' ";

        }
        if(pageable.getSort() !=null){
            sql+="order by a."+(pageable.getSort().toString().replace(':',' '));
            System.out.println(pageable.getSort().toString().replace(':',' '));
        }
        Query query = entityManager.createQuery(sql);
        if(null != exceptDateS&&null!=exceptDateE){
            query.setParameter("exceptDateS",exceptDateS,TemporalType.DATE);
            query.setParameter("exceptDateE",exceptDateE,TemporalType.DATE);
        }
        if(null != estimatedTimeS&&null!=estimatedTimeE){
            query.setParameter("estimatedTimeS",estimatedTimeS,TemporalType.DATE);
            query.setParameter("estimatedTimeE",estimatedTimeE,TemporalType.DATE);
        }

        return query.getResultList();
    }

    public Page<AppointmentPo> queryAppointmnetPlane(Pageable pageable, String flightInfoId, Date exceptDateS,Date exceptDateE, Date estimatedTimeS,  Date estimatedTimeE,String importOrExport){
        String sql = "select a from AppointmentPo a left join fetch  a.flightPlane f left join fetch f.flightInfo left join a.flightInfo where 1=1  ";
        if(null != exceptDateS&&null!=exceptDateE){
            sql += " and a.appoDate  between :exceptDateS and :exceptDateE";
        }
        if(null != estimatedTimeS&&null!=estimatedTimeE){
            sql += " and a.estimatedTime between  :estimatedTimeS  and :estimatedTimeE ";
        }
        if(StringUtils.isNotBlank(importOrExport)){
            sql+= " and  a.appProperty = '"+importOrExport+"' ";
        }

        if(StringUtils.isNotBlank(flightInfoId) ){
            sql += " and a.flightInfo.flightInfoId  = '"+flightInfoId+"' ";

        }
        if(pageable.getSort() !=null){
            sql+="order by a."+(pageable.getSort().toString().replace(':',' '));
            System.out.println(pageable.getSort().toString().replace(':',' '));
        }
        Query query = entityManager.createQuery(sql);
        if(null != exceptDateS&&null!=exceptDateE){
            query.setParameter("exceptDateS",exceptDateS,TemporalType.DATE);
            query.setParameter("exceptDateE",exceptDateE,TemporalType.DATE);
        }
        if(null != estimatedTimeS&&null!=estimatedTimeE){
            query.setParameter("estimatedTimeS",estimatedTimeS,TemporalType.DATE);
            query.setParameter("estimatedTimeE",estimatedTimeE,TemporalType.DATE);
        }

        return  new PageImpl<AppointmentPo>(query,pageable);


    }

    public List<AppointmentPo> findAllAppointOfSignin(String flightInfoId,String  planeId,String originating,String destination,Date appoDate,String appProperty){
        Query query = entityManager.createQuery("select  a from AppointmentPo  a where a.flightPlane.planeId = :planeId or" +
                "(a.originating = :originating and a.destination = :destination and a.appoDate = :appoDate and a.appProperty = :appProperty and a.flightInfo.flightInfoId = :flightInfoId)");
        query.setParameter("flightInfoId",flightInfoId);
        query.setParameter("planeId",planeId);
        query.setParameter("originating",originating);
        query.setParameter("destination",destination);
        query.setParameter("appProperty",appProperty);
        query.setParameter("appoDate",appoDate, TemporalType.DATE);
        return query.getResultList();

//        Specification query = new Specification<AppointmentPo>(){
//
//            @Override
//            public Predicate toPredicate(Root<AppointmentPo> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
//                Predicate predicate = cb.equal(root.get("flightInfo").get("flightInfoId"),flightInfoId);
//                predicate = cb.and(predicate,cb.equal(root.get("originating"),originating));
//                predicate = cb.and(predicate,cb.equal(root.get("destination"),destination));
//                predicate=cb.and(predicate,cb.equal(root.get("appProperty"),appProperty));
//                predicate=cb.and(predicate,cb.equal(root.get("appoDate"),appoDate));
//                return predicate;
//            }
//        };
//        return this.appointmentDao.findAll(query);
    }

    public List findAllAppoUnit(){

        Query query= entityManager.createQuery("select distinct a.appoUnit from AppointmentPo a");
        return query.getResultList();
    }

}

